Usaremos, para este experimento, dois filtros como módulos de processamento M1 e M2, sendo M1 um filtro PB com frequência de corte em 400Hz e m2 um PA com frequência de corte em 2400Hz. Utilizaremos a versão streaming da biblioteca Essentia. Abaixo, para fins de referência, podemos escutar o áudio original e resultado do processamento do áudio original por cada um dos filtros, de modo independente:
import essentia
from essentia.streaming import *
import IPython
filename = 'cello-double.wav'
# áudio original
IPython.display.Audio(filename)
# Audio original após processamento de filtro PB (M1)
IPython.display.Audio('lpf.wav')
# Audio original após processamento de filtro PA (M2)
IPython.display.Audio('hpf.wav')
Agora, aplicaremos os dois filtros em série, processando inicialmente pelo filtro PB e depois pelo PA:
loader = essentia.streaming.MonoLoader(filename=filename)
lpf_serial_hpf_filename = 'lpf_serial_hpf.wav'
writer = MonoWriter(filename=lpf_serial_hpf_filename)
lpf = LowPass(cutoffFrequency=400)
hpf = HighPass(cutoffFrequency=2400)
# processa o fluxo de audio pelos módulos criados EM SÉRIE
loader.audio >> lpf.signal >> hpf.signal >> writer.audio
essentia.run(loader)
# reproduz o áudio resultante
IPython.display.Audio(lpf_serial_hpf_filename)
Também criaremos uma segunda versão em série, passando inicialmente por PA e depois por PB:
loader = essentia.streaming.MonoLoader(filename=filename)
lpf_serial_hpf_filename = 'lpf_serial_hpf2.wav'
writer = MonoWriter(filename=lpf_serial_hpf_filename)
lpf = LowPass(cutoffFrequency=400)
hpf = HighPass(cutoffFrequency=2400)
# processa o fluxo de audio pelos módulos criados EM SÉRIE
loader.audio >> hpf.signal >> lpf.signal >> writer.audio
essentia.run(loader)
# reproduz o áudio resultante
IPython.display.Audio(lpf_serial_hpf_filename)
Agora, processaremos o sinal em paralelo nos filtros PA e PB, e depois adicionamos o resultados em um mesmo arquivo:
loader = essentia.streaming.MonoLoader(filename=filename)
lpf_parallel_hpf_filename = 'lpf_parallel_hpf.wav'
writer = MonoWriter(filename=lpf_parallel_hpf_filename)
lpf = LowPass(cutoffFrequency=400)
hpf = HighPass(cutoffFrequency=2400)
pool = essentia.Pool()
# processa o fluxo de audio pelos módulos criados EM SÉRIE
loader.audio >> lpf.signal >> (pool, 'lpf')
loader.audio >> hpf.signal >> (pool, 'hpf')
essentia.run(loader)
# mixa os dois áudios e cria o arquivo final
vector_input = VectorInput(pool['lpf'] + pool['hpf'])
vector_input.data >> writer.audio
essentia.run(vector_input)
# reproduz o áudio resultante
IPython.display.Audio(lpf_parallel_hpf_filename)
Foi escolhida como amostra original uma pequena frase de violoncelo, por haver nela bastante informação em boa parte do espectro, o que nos permite escutar mais claramente o resultado do processamento dos filtros. Para fins de melhor comparação, foram extraídas previamente amostras do áudio resultante do processamento individual do audio original por cada um dos filtros M1 e M2.
Abaixo, discutiremos o resultado perceptível após o processamento por M1 e M2 dos dois modos diferentes, em série e em paralelo.
O resultado perceptível da aplicação dos filtros em série foi muito semelhante entre as duas versões (PA->PB e PB->PA), e ambas bastante diferentes da versão original. Independente da ordem da aplicação dos filtros, as duas versões encontram-se com a mesma 'ausência' nos graves e nos agudos. Faz sentido, considerando o processo de consecutivas atenuações pelo qual o audio original passou.
O resultado perceptível é diferente do áudio original e também diferente resultado do processamento em série. De fato, os materiais das bandas graves e agudas não são removidos após a adição dos sinais A e B resultantes do processamento dos filtros, pois o que falta em A ainda está em B e vice-versa. Neste caso, o efeito produzido pelo processamento em paralelo concentra-se nas frequências que estão no centro do espectro, onde deverá haver excitação de faixas de frequências, e não só atenuação das mesmas.
Abaixo foram novamente adicionados os áudios, por praticidade.
IPython.display.Audio(filename)
IPython.display.Audio('lpf.wav')
IPython.display.Audio('hpf.wav')
IPython.display.Audio(lpf_serial_hpf_filename)
IPython.display.Audio(lpf_parallel_hpf_filename)